/*
日志宏的定义
json的的序列化和返序列化的实现
uuid的生成
*/
#pragma once

#include <iostream>
#include <time.h>
#include <stdio.h>
#include <sstream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>

#include<time.h>
#include<stdio.h>
#include<random>
#include<chrono>
#include<iomanip>
#include<atomic>
namespace bitRPC // namespace  bitRPC
{
    #define LDBUG 0
    #define LINFO 1
    #define LERR 2

    #define LDEFUAT LDBUG
    #define LOG(Leve, format, ...)                                                                           \
        {                                                                                                    \
            if (Leve >= LDEFUAT)                                                                             \
            {                                                                                                \
                time_t t = time(NULL);                                                                       \
                struct tm *lt = localtime(&t);                                                               \
                char timestr[32] = {0};                                                                      \
                strftime(timestr, 31, "%m-%d %T", lt);                                                       \
                std::fprintf(stdout, "[%s][%s:%d]" format "\n", timestr, __FILE__, __LINE__, ##__VA_ARGS__); \
            }                                                                                                \
        }

    #define DLOG(format, ...) LOG(LDBUG, format, ##__VA_ARGS__);
    #define ILOG(format, ...) LOG(LINFO, format, ##__VA_ARGS__);
    #define ELOG(format, ...) LOG(LERR, format, ##__VA_ARGS__);
        class JSON
        {
            // 实现数据的序列化
        public:
            static bool serialize(const Json::Value &val, std::string &body)
            {
                std::stringstream ss;
                // 先实例化⼀个⼯⼚类对象
                Json::StreamWriterBuilder swb;
                // 通过⼯⼚类对象来⽣产派⽣类对象
                std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
                int ret = sw->write(val, &ss);
                if (ret != 0)
                {
                    DLOG("json serialize failed!\n");
                    return false;
                }
                body = ss.str();
                return true;
            }
            // 实现json字符串的反序列化
           static bool unserialize(const std::string &body, Json::Value &val)
            {
                // 实例化⼯⼚类对象
                Json::CharReaderBuilder crb;
                // ⽣产CharReader对象
                std::string errs;
                std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
                bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val,
                                    &errs);
                if (ret == false)
                {
                    ELOG("json unserialize failed : ", errs.c_str());
                    return false;
                }
                return true;
            }
        };
    class UUID{
        public:
            static std::string uuid()
            {
                //生成一个随机数的种子
            std::random_device rd;
            //用种子生成一个随机数
            std::mt19937 gen(rd());
            //构造一个限定数据范围的对象
            std::uniform_int_distribution<int> dist(0,255);
            // 生成8个随机数，按照特定格式组织成为16进制数字字符串
            std::stringstream ss;
            for(int i=0;i<8;i++)
            {
                if(i==4||i==6){ ss<<'-';}
                ss<<std::hex<<std::setw(2)<<std::setfill('0')<<dist(gen);
            }
            // 定义一个8字节序号，逐字节组织成为16进制数字字符串 
            // 550e8400-e29b-41d4-a716-446655440000。 
            ss<<'-';
            static std::atomic<size_t> sep(0);
            size_t cur=sep.fetch_add(1);
            for(int i=7;i>=0;i--)
            {
                if(i==5){
                    ss<<'-';
                }
                ss<<std::setw(2)<<std::setfill('0')<<std::hex<<((cur>>(i*8))&0xFF);
            }
            return ss.str();
        }
    };
}